var controlSpreadsheetId = "ttsJKpzSFCcpaxPH8KbM6MA";
var inputSpreadsheetId = "tyX1gz69VZmebrSM71svlKg";

// Identify rows in the control spreadsheet.
var ssLabelRow = 1;
var ssTypeRow = 2;

// This function executes for a Google Sites page.
function doGet(e) {
  // Create a UI application.
  var app = UiApp.createApplication();
  
  // Open the control spreadsheet.
  var ss = SpreadsheetApp.openById(controlSpreadsheetId);
  var sh = ss.getSheets()[0];
  var nCols = sh.getLastColumn();
  var colNames = sh.getRange(ssLabelRow, 1, 1, nCols).getValues()[0];
  var colTypes = sh.getRange(ssTypeRow, 1, 1, nCols).getValues()[0];
  var col;  // loop index
  
  // Create a flow panel to contain everything.
  var outerPanel = app.createFlowPanel();
  
  // Create singleton data entry widgets.
  var provider = app.createTextBox().setSize('20em', '1.5em').setName('provider');
  var providerWrap = app.createGrid(1, 2);
  providerWrap.setText(0, 0, 'Provider:').setWidget(0, 1, provider);
  
  // Create a data entry grid.
  var grid = app.createGrid(2, nCols).setBorderWidth(1).setStyleAttribute('marginTop', '12pt');
  // Set column headers in the first row.
  for (col = 0; col < nCols; col++)
    grid.setWidget(0, col, app.createLabel(colNames[col]).setStyleAttribute('textAlign', 'center').setStyleAttribute('fontSize', 'small'));
  // Create data entry widgets in the second row.
  var rowWidgets = widgetsForRow(app, sh, 1);
  for (col = 0; col < nCols; col++)
    grid.setWidget(1, col, rowWidgets[col]);
  
  // Create a submit button.
  var submit = app.createButton('submit');
  var submitHandler = app.createServerClickHandler("thanks");
  submit.addClickHandler(submitHandler);
  submitHandler.addCallbackElement(outerPanel);
  
  // Put everything together.
  app.add(outerPanel.add(providerWrap).add(grid).add(submit));
  
  return app;
}

// Generate and return a list of dates for a calendar week
// (Sun through Sat) that includes a given date.
function thisWeek(includeDate) {
  var msPerDay = 1000 * 60 * 60 * 24;
  // Find Saturday, 12AM.
  var sat = new Date(includeDate.getTime() + (6 - includeDate.getDay()) * msPerDay);
  sat = new Date(sat.getFullYear(), sat.getMonth(), sat.getDate());
  var dates = new Array(7);
  for (var day = 6; day >= 0; day--) {
    dates[day] = new Date(sat.getTime() - (6 - day) * msPerDay);
  }
  return dates;
}

// Convert a column label to a valid control name.
function validName(label) {
  return label.replace(/\W/g, '_');
}

// Return the input control name for a grid row and column.
// eg, Column_Label_1
function ctlName(sh, gridRow, gridCol) {
  return validName(sh.getRange(ssLabelRow, gridCol + 1).getValue()) + "_" + gridRow;
}

// Create and return a drop-down date menu for a particular column.
function dateMenu(app, sh, gridRow, gridCol) {
  var m = app.createListBox().setName(ctlName(sh, gridRow, gridCol));
  var dates = thisWeek(new Date());
  for (var i = 0; i < dates.length; i++) {
    m.addItem(dates[i].toDateString());
  }
  return m;
}

// Construct and return a custom drop-down menu.
function menu(app, sh, gridRow, gridCol) {
  var ssCol = gridCol + 1;
  var name = sh.getRange(ssLabelRow, ssCol).getValue() + "_" + gridRow;
  // Retrieve menu items from underneath the 'select' keyword in the spreadsheet.
  var ssRow = ssTypeRow + 1;
  var items = [];
  var value;
  while (value = sh.getRange(ssRow++, ssCol).getValue()) {
    items.push(value);
  }
  // Create a list box widget.
  var m = app.createListBox().setName(ctlName(sh, gridRow, gridCol));
  for (var i = 0; i < items.length; i++) {
    if (!i) m.addItem('');  // add a blank item at the top of the list
    m.addItem(items[i]);
  }
  return m;
}

// Create and return a set of data entry widgets for a particular row in the grid.
function widgetsForRow(app, sh, gridRow) {
  var nCols = sh.getLastColumn();
  var colTypes = sh.getRange(ssTypeRow, 1, 1, nCols).getValues()[0];
  var widgets = new Array(nCols);
  var i;  // widget index, 0-based (ss columns are 1-based, grid columns 0-based)
  for (var i = 0; i < nCols; i++) {
    switch (colTypes[i].toLowerCase()) {
      case 'date':
        widgets[i] = dateMenu(app, sh, gridRow, i).setName(ctlName(sh, gridRow, i));
        break;
      case 'select':
        widgets[i] = menu(app, sh, gridRow, i).setName(ctlName(sh, gridRow, i));
        break;
      case 'text':
      case 'number':
        widgets[i] = app.createTextBox().setName(ctlName(sh, gridRow, i));
        break;
    }
  }
  return widgets;
}

// Callback function for submit button onclick handler.
function thanks(panel) {
  // Reestablish the UI application.
  var app = UiApp.getActiveApplication();
  var provider = panel.parameter.provider;  // provider name

  // Open the control spreadsheet.
  var controlSs = SpreadsheetApp.openById(controlSpreadsheetId);
  var controlSh = controlSs.getSheets()[0];
  var nCols = controlSh.getLastColumn();
  var colNames = controlSh.getRange(ssLabelRow, 1, 1, nCols).getValues()[0];
  var colTypes = controlSh.getRange(ssTypeRow, 1, 1, nCols).getValues()[0];
  var col;  // loop index

  // Look for input grid rows.
  var date1 = new Date(panel.parameter.Date_1);
  var colValues = new Array(nCols);  // input values from one row
  for (col = 0; col < nCols; col++) {
    colValues[col] = panel.parameter[ctlName(controlSh, 1, col)];
    if (colTypes[col].toLowerCase() == 'date')
      colValues[col] = new Date(colValues[col]);
  }
  
  // Open the data input spreadsheet.
  var inputSs = SpreadsheetApp.openById(inputSpreadsheetId);
  var inputSh = inputSs.getSheets()[0];
  
  // Store data.
  var submitted = new Date();
  colValues.splice(0, 0, provider, submitted);
  inputSh.getRange(inputSh.getLastRow() + 1, 1, 1, colValues.length).setValues([colValues]);
    
  app.add(app.createLabel('Thanks, ' + (provider ? provider : 'nobody') + '.'));
  return app.close();
}

// Add a message to the panel, for debugging.
function msg(app, t) {
  app.add(app.createLabel(t));
}
